package com.gitee.wsl.security.password

import com.gitee.wsl.struct.generator.Generator
import com.gitee.wsl.struct.generator.StringGeneratorWithLength
import kotlin.math.max
import kotlin.random.Random

interface PasswordGenerator {
     fun generate(
         uppercaseLength: Int = 0,
         digitLength: Int = 0,
         lowercaseLength: Int = 0,
         specialLength: Int = 0,
         totalLength: Int = 10,
    ): String
}

typealias DigitRandom= StringGeneratorWithLength
typealias LowercaseRandom= StringGeneratorWithLength
typealias SpecialRandom= StringGeneratorWithLength
typealias UppercaseRandom= StringGeneratorWithLength

class DefaultPasswordGenerator(
    private val digitRandom: DigitRandom = Generator.DigitRandom,
    private val lowercaseRandom: LowercaseRandom = Generator.LowercaseRandom,
    private val specialRandom: SpecialRandom = Generator.SpecialRandom,
    private val uppercaseRandom: UppercaseRandom = Generator.UppercaseRandom
) : PasswordGenerator {
    override  fun generate(
        uppercaseLength: Int,
        digitLength: Int,
        lowercaseLength: Int,
        specialLength: Int,
        totalLength: Int,
    ): String {
        val lowLength = max(totalLength-uppercaseLength-digitLength-specialLength,lowercaseLength)

        val password = buildString {
            if(digitLength > 0)
              append(digitRandom(digitLength))

            if(uppercaseLength > 0)
              append(uppercaseRandom(uppercaseLength))

            append(lowercaseRandom(lowLength))

            if(specialLength > 0)
              append(specialRandom(specialLength))

        }
        return password.toList().shuffled().joinToString("")
    }

    companion object{
        val instance = DefaultPasswordGenerator()
    }
}

fun Random.generatePassword(length: Int = 8,
                            uppercaseLength: Int = 0,
                            digitLength: Int = 0,
                            lowercaseLength: Int = 0,
                            specialLength: Int = 0,
                            passwordGenerator: PasswordGenerator = DefaultPasswordGenerator.instance
) = passwordGenerator.generate(uppercaseLength, digitLength, lowercaseLength, specialLength, length)

fun Password.random(length: Int = 8,
                    uppercaseLength: Int = 0,
                    digitLength: Int = 0,
                    lowercaseLength: Int = 0,
                    specialLength: Int = 0,
                    passwordGenerator: PasswordGenerator = DefaultPasswordGenerator.instance
):String{
    return passwordGenerator.generate(uppercaseLength, digitLength, lowercaseLength, specialLength, length)
}